<template>
  <div>
    <a-upload
        name="cropper"
        class="cropper-uploader"
        :show-upload-list="false"
        :before-upload="beforeUpload"
        :custom-request="function(){}"
        @change="handleChange"
    >
      <img v-if="imageUrl" :src="localUrl + imageUrl" alt="avatar" style="width: 100%;height: 100px"/>
      <div v-else>
        <loading-outlined v-if="loading"></loading-outlined>
        <plus-outlined v-else></plus-outlined>
        <div class="ant-upload-text">上传</div>
      </div>
    </a-upload>
    <a-modal v-model:visible="visible" title="图片裁剪" @ok="cropperOk" width="50%">
      <div style="width:100%;height:500px">
        <vueCropper
            ref="cropperRef"
            :img="cropUrl"
            mode="contain"
            :autoCrop="true"
            :autoCropWidth="700"
            :autoCropHeight="220"
            :canMoveBox="true"
            :outputSize="1"
            outputType="jpeg"
        ></vueCropper>
      </div>
      <template #footer>
        <a-button key="back" @click="cropperCancel">取消</a-button>
        <a-button key="resume" :loading="loading" @click="doResume">还原</a-button>
        <a-button key="crop" :loading="loading" @click="doCrop">裁剪</a-button>
        <a-button key="submit" type="primary" :loading="loading" @click="cropperOk">确定</a-button>
      </template>
    </a-modal>
  </div>
</template>

<script>
import { computed, onMounted, ref } from "vue";

import 'vue-cropper/dist/index.css'
import { VueCropper } from "vue-cropper";
import { localUrl } from "@/config/settings";
import { message } from "ant-design-vue";
import { upload } from "@/api/file";
import { base64toFile, getBase64 } from "@/utils";
import { CODEENUM } from "@/config";

export default {
  name: "index",
  components: {
    VueCropper,
  },
  props: {
    file: {
      type: String,
      default: ""
    },
  },
  setup(props, { emit }) {
    const cropperRef = ref(null);
    // 裁剪弹窗
    const visible = ref(false);
    // 备份源文件
    const originalUrl = ref('');
    // 加载状态
    const loading = ref(false);

    const imageUrl = ref(props.file);

    // 裁剪后的图片base64 url
    const cropUrl = ref('');


    const cropperCancel = () => {
      cropUrl.value = '';
      originalUrl.value = '';
      visible.value = false;
    };


    // 还原图片
    const doResume = () => {
      cropUrl.value = originalUrl.value;
    }

    // 裁剪
    const doCrop = async () => {
      return new Promise((resolve) => {
        cropperRef.value.getCropData(data => {
          cropUrl.value = data
          resolve();
        })
      })
    };

    // 确认
    const cropperOk = async () => {
      await doCrop();
      const fileObj = base64toFile(cropUrl.value, '文章封面.jpg');
      const formData = new FormData()
      formData.append('file', fileObj)

      const { data, code } = await upload(formData)
      if (code !== CODEENUM.OP_SUCCESS) return;
      imageUrl.value = `/${data[0]?.dir}/${data[0]?.url}`;
      visible.value = false
      emit('update:file', imageUrl.value)
    };

    // 图片上传事件
    const handleChange = ({ file }) => {
      loading.value = true;
      getBase64(file, base64Url => {
        originalUrl.value = base64Url;
        cropUrl.value = base64Url;
        loading.value = false;
        visible.value = true;
      });
    };
    // 图片格式校验
    const beforeUpload = file => {
      // 检验图片类型及大小
      const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
      if (!isJpgOrPng) {
        message.error('仅支持上传jpg或png图片!');
      }
      const isLt2M = file.size / 1024 / 1024 < 4;
      if (!isLt2M) {
        message.error('图片大小必须小于 4MB!');
      }
      return !isJpgOrPng && isLt2M;
    };

    return {
      localUrl,
      cropperRef,


      visible,

      cropUrl,
      imageUrl,
      loading,
      handleChange,
      beforeUpload,

      doResume,
      doCrop,

      cropperOk,
      cropperCancel
    }
  }
}
</script>

<style lang="less" scoped>
.cropper-uploader {
  display: block;
  width: 100%;
  height: 100px;

  border: 1px solid #d9d9d9;
  border-radius: 2px;
  text-align: center;
  cursor: pointer;
  transition: all .3s;
  overflow: hidden;

  &:hover {
    border-color: var(--antd-wave-shadow-color);
    background-color: var(--w-e-textarea-slight-bg-color);
    //--w-e-textarea-handler-bg-color: #4290f7;
  }

  :deep(.ant-upload) {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
  }
}
</style>
